Skip to content

Document how Element#attribute matches a namespace - #360

Merged
kou merged 1 commit into
ruby:masterfrom
naitoh:document_attribute_namespace_matching
Aug 17, 2026
Merged

Document how Element#attribute matches a namespace#360
kou merged 1 commit into
ruby:masterfrom
naitoh:document_attribute_namespace_matching

Conversation

@naitoh

@naitoh naitoh commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

GitHub: Fix GH-151

REXML::Element#attribute matches its +namespace+ argument loosely: an unprefixed attribute is taken to be in the default namespace, and a namespace that no prefix is bound to falls back to the unprefixed attribute.

<root xmlns='ns0' a='a'/>

attribute("a", "ns0")    -> a='a'
attribute("a", "nosuch") -> a='a'

The XML Namespaces specification says an unprefixed attribute has no namespace and does not take the default one, so neither of those should match. The
behavior is kept for compatibility -- it is what tickets 102 and 121 asked for, and the tests for both are still in place -- but nothing said so, which has left people reading the method unsure whether what they saw was the contract or a bug.

Say it in the documentation of both methods, and point each at the other: REXML::Attributes#get_attribute_ns matches as the XML Namespaces specification says and is what to reach for when the namespace has to be matched strictly. It has behaved that way at least as far back as GH-151, but that discussion never mentioned it.

Reported by Hiroya Fujinami. Thanks!!!

REXML::Element#attribute matches its +namespace+ argument loosely: an
unprefixed attribute is taken to be in the default namespace, and a
namespace that no prefix is bound to falls back to the unprefixed
attribute.

    <root xmlns='ns0' a='a'/>

    attribute("a", "ns0")    -> a='a'
    attribute("a", "nosuch") -> a='a'

The XML Namespaces specification says an unprefixed attribute has no
namespace and does not take the default one, so neither of those should
match.  The
behavior is kept for compatibility -- it is what tickets 102 and 121
asked for, and the tests for both are still in place -- but nothing said
so, which has left people reading the method unsure whether what they
saw was the contract or a bug.

Say it in the documentation of both methods, and point each at the
other: REXML::Attributes#get_attribute_ns matches as the XML Namespaces
specification says and is what to reach for when the namespace has to be
matched strictly.  It has behaved that way at least as far back as rubyGH-151, but
that discussion never mentioned it.

GitHub: rubyGH-151
@naitoh

naitoh commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Based on the discussion below, we will update the documentation for REXML::Element#attribute and REXML::Attributes#get_attribute_ns to include the current behavior regarding namespace specification as part of the specification.

@naitoh
naitoh requested a review from kou August 17, 2026 08:40
@kou
kou requested a lite review from Copilot August 17, 2026 08:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@kou
kou merged commit 141f4a4 into ruby:master Aug 17, 2026
71 checks passed
@naitoh
naitoh deleted the document_attribute_namespace_matching branch August 17, 2026 08:55
kou pushed a commit that referenced this pull request Aug 31, 2026
GH-360 documented `REXML::Element#attribute` as matching a namespace
loosely, and said an unprefixed attribute is taken to be in the default
namespace. GH-357 made the method ask
REXML::Attributes#get_attribute_ns first, so that is now only true when
nothing matches strictly:

    <root xmlns='ns0' xmlns:p='ns0' a='A' p:a='PA'/>

    attribute("a", "ns0")   ->  p:a='PA', not a='A'

The two examples in the note still hold, because neither document has a
prefixed attribute of the same local name for the strict match to find.
It is the rule stated around them that no longer holds: an unprefixed
attribute is taken to be in the default namespace only when nothing
matches strictly.

Describe the method the way it now works -- strict first, then the
compatibility fallback -- and add the example above, which is the only
place the change is visible. Say of get_attribute_ns that it matches
strictly and only strictly, rather than pointing at it as the way to
match strictly, now that Element#attribute starts there too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants